package com.google.code.jtasks.client.services;

import com.google.code.jtasks.client.state.ClientState;
import com.google.code.jtasks.common.data.Task;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.MediaType;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Реализация {@link TaskService}, использующая Jersey для соединения с RESTful-вебсервисом.
 */
public class JerseyRemoteTaskService implements TaskService {
    private static final Logger LOG = LoggerFactory.getLogger(JerseyRemoteTaskService.class);

    private final Client client;
    private final ClientState state;

    @Inject
    JerseyRemoteTaskService(Client client, ClientState state) {
        this.client = client;
        this.state = state;
    }

    @Override
    public List<Task> loadAllTasks() {
        WebResource resource = client.resource(state.serviceUri());
        try {
            return resource.accept(MediaType.APPLICATION_JSON_TYPE).get(new GenericType<List<Task>>(){});
        } catch (UniformInterfaceException e) {
            LOG.error("Error retrieving task list", e);
            return Collections.emptyList();
        }
    }

    @Override
    public void addTask(Task task) {
        WebResource resource = client.resource(state.serviceUri());
        try {
            resource.type(MediaType.APPLICATION_JSON_TYPE).post(task);
        } catch (UniformInterfaceException e) {
            LOG.error("Error posting task", e);
        }
    }

    @Override
    public void deleteTask(Task task) {
        checkArgument(task.id.isPresent(), "Task id is not present");

        // service_uri/{task id}, e.g. http://localhost:8080/tasks/35338483923
        WebResource resource = client.resource(state.serviceUri().resolve(task.id.get()));
        try {
            resource.type(MediaType.APPLICATION_JSON_TYPE).delete();
        } catch (UniformInterfaceException e) {
            LOG.error("Error deleting task", e);
        }
    }

    /**
     * {@inheritDoc}
     *
     * <p>Следует перенести эту функциональность в серверную часть.</p>
     */
    @Override
    public List<Task> findTaskByName(String name) {
        Pattern pattern = Pattern.compile(Pattern.quote(name), Pattern.CASE_INSENSITIVE);

        List<Task> tasks = Lists.newArrayList(loadAllTasks());
        for (Iterator<Task> it = tasks.iterator(); it.hasNext(); ) {
            Task task = it.next();
            if (!pattern.matcher(task.name).find()) {
                it.remove();
            }
        }

        return tasks;
    }
}
